package util

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"

	"go.uber.org/zap"
	"ops.alert.center.service/internal/middleware"
	"ops.alert.center.service/internal/model"
)

type Node struct {
	// Val   UserDetail
	Val   model.UserDetail
	Left  *Node
	Right *Node
}

type BinarySearchTree struct {
	Root *Node
}

// 初始化二叉排序树
func NewBinarySearchTree(node *Node) *BinarySearchTree {
	return &BinarySearchTree{
		Root: node,
	}
}

var ThisUserTokenData model.UserToken
var ThisDepartmentOutData model.DepartmentOutData
var Usertree = NewBinarySearchTree(nil)
var ThisWaitgroup = new(sync.WaitGroup)
var ThisDepartmentMutex = &sync.Mutex{}
var ThisTreeMutex = &sync.Mutex{}
var ThisuserInsertMutex = &sync.Mutex{}

var Count, InsertCount int = 0, 0

//获取通讯录token
func GetAccessToken() error {
	var thiserror error
	defer func() {
		if err := recover(); err != nil {
			middleware.Logger.Info("GetAccessToken error",
				zap.String("error message->", thiserror.Error()),
			)
		}
	}()
	// 获取企业微信通信录的token
	var url = fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s",
		middleware.WechatUserCorpid, middleware.WechatUserCorpSecret)
	res, thiserror := http.Get(url)
	defer res.Body.Close()

	robots, thiserror := ioutil.ReadAll(res.Body)
	middleware.Logger.Info("GetAccessToken string",
		zap.String("usertoken string message is ->", string(robots)),
	)
	thiserror = json.Unmarshal(robots, &ThisUserTokenData)
	return nil
}

// 获取部门的列表
func GetDepartmentList() error {
	var thiserror error
	GetAccessToken()
	defer func() {
		if err := recover(); err != nil {
			middleware.Logger.Info("GetDepartmentList error",
				zap.String("error message->", thiserror.Error()),
			)
		}
	}()
	if len(ThisUserTokenData.Access_token) > 0 {
		var url = fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%s",
			ThisUserTokenData.Access_token)
		res, thiserror := http.Get(url)
		defer res.Body.Close()
		robots, thiserror := ioutil.ReadAll(res.Body)
		thiserror = json.Unmarshal(robots, &ThisDepartmentOutData)
		fmt.Println(thiserror)
		return nil
	}
	return nil
}

//根据部门id获取企业微信人员的数据
func GetUsersBydepartmentID(departmentId int, token string) {
	defer ThisWaitgroup.Done()
	ThisDepartmentMutex.Lock()
	Count = Count + 1
	var thiserror error
	defer func() {
		if err := recover(); err != nil {
			middleware.Logger.Info("GetUsersBydepartmentID error",
				zap.String("error message->", thiserror.Error()),
			)
		}
	}()
	var thisUserData model.DepartmentUserOutData
	var url = fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=%s&department_id=%d&fetch_child=0",
		token, departmentId)
	res, thiserror := http.Get(url)
	defer res.Body.Close()
	robots, thiserror := ioutil.ReadAll(res.Body)
	thiserror = json.Unmarshal(robots, &thisUserData)
	for _, v := range thisUserData.Userlist {
		go InsertwechatdataRedis(v)
	}
	ThisDepartmentMutex.Unlock()
}

// 拼接企业微信人员数据至链表
func GetWechatData() {
	fmt.Println(time.Now())
	Usertree = NewBinarySearchTree(nil)
	GetDepartmentList()
	ThisWaitgroup.Add(len(ThisDepartmentOutData.Department))
	fmt.Println("部门长度是:", len(ThisDepartmentOutData.Department))
	for _, v := range ThisDepartmentOutData.Department {
		go GetUsersBydepartmentID(v.ID, ThisUserTokenData.Access_token)
	}
	ThisWaitgroup.Wait()
	fmt.Println(time.Now())
}

//创建二叉树的节点
func NewNode(value model.UserDetail) *Node {
	return &Node{value, nil, nil}
}

//前序遍历二叉树
func FinduserIDbyName(n *Node, name string) {
	if n != nil {
		if n.Val.Name == name {
			fmt.Println("本次员工的数据是:", n.Val.Mobile, n.Val.Name, n.Val.UserID, n.Val.Email)
		} else {
			FinduserIDbyName(n.Left, name)
			FinduserIDbyName(n.Right, name)
		}
	}
}

func (tree *BinarySearchTree) Insert(data model.UserDetail) error {
	ThisuserInsertMutex.Lock()
	InsertCount = InsertCount + 1
	ThisuserInsertMutex.Unlock()
	if node := tree.Root; node == nil {
		// 二叉排序树为空，则初始化
		tree.Root = NewNode(data)
		return nil
	} else {
		// 否则找到要插入的位置插入新的节点
		for node != nil {
			thisMobile, _ := strconv.Atoi(data.Mobile)
			thisNodeMobile, _ := strconv.Atoi(node.Val.Mobile)
			if thisMobile < thisNodeMobile {
				if node.Left == nil {
					node.Left = NewNode(data)
					break
				}
				node = node.Left
			} else if thisMobile > thisNodeMobile {
				if node.Right == nil {
					node.Right = NewNode(data)
					break
				}
				node = node.Right
			} else {
				return errors.New("对应数据已存在，请勿重复插入")
			}
		}
		return nil
	}
}

//int切片去重
func RemoveRepeatedElement(arr []int) (newArr []int) {
	newArr = make([]int, 0)
	for i := 0; i < len(arr); i++ {
		repeat := false
		for j := i + 1; j < len(arr); j++ {
			if arr[i] == arr[j] {
				repeat = true
				break
			}
		}
		if !repeat {
			newArr = append(newArr, arr[i])
		}
	}
	return
}

func Substr(str string, start int, length int) string {
	rs := []rune(str)
	rl := len(rs)
	end := 0

	if start < 0 {
		start = rl - 1 + start
	}
	end = start + length

	if start > end {
		start, end = end, start
	}

	if start < 0 {
		start = 0
	}
	if start > rl {
		start = rl
	}
	if end < 0 {
		end = 0
	}
	if end > rl {
		end = rl
	}

	return string(rs[start:end])
}

func isValueInList(value int, list []int) bool {
	for _, v := range list {
		if v == value {
			return true
		}
	}
	return false
}

func ContainString(blackSlice []string, alertcontent string) bool {
	for _, words := range blackSlice {
		if strings.Contains(alertcontent, words) {
			return true
		}
	}
	return false
}
